#include "word_filter.h"
#include "util.h"
#include "json/json.h"
#include <algorithm>

#define MCHECK_ACSII_1(c)		(c>=32 && c<=47)			//space!"#$%&'()*+,-./
#define MCHECK_ACSII_2(c)		(c>=58 && c<=64)			//:;<=>?@
#define MCHECK_ACSII_3(c)		(c>=91 && c<=96)			//[\]^_`
#define MCHECK_ACSII_4(c)		(c>=123 && c<=127)			//{|}~
#define MCHECK_ASCII_Tab(c)		(9 == c)					//Tab
#define MCHECK_ASCII_Num(c)		(c>=48 && c<=57)			//0-9
#define MCHECK_ASCII_Alpha(c)	((c>=65 && c<=90) || (c>=97 && c<=122))

WordFilter::WordFilter()
{

}

WordFilter::~WordFilter()
{

}

bool WordFilter::init()
{
    std::string file_path = fmt_cstr("%s/cfg/wordfilter.txt", get_deploy());

    const char* file = load_file(file_path.c_str());
    if (strlen(file) == 0) {
        UTIL_LOG(E, "cfg_file_t::load file %s noexist", file_path.c_str());
        return false;
    }

    Json::Value bc = to_json(file);
    if (bc.empty() || bc.isNull()) {
        UTIL_LOG(E, "cfg_file_t::load file %s empty", file_path.c_str());
        return false;
    }

    uint16_t flag;
    uint16_t tmp;

    for(uint32_t i=0; i < bc["item"].size(); ++i)
    {
        const Json::Value& item = bc["item"].get(i, Json::nullValue);

        _filters.push_back(item.get("text", "").asCString());

        flag = 0;

        tmp = item.get("createrole", 0).asUInt();
        flag |= tmp << 2;

        tmp = item.get("naming", 0).asUInt();
        flag |= tmp << 4;

        _flags.push_back(flag);
    }

	return true;
}

bool WordFilter::checkName( const char* szName, EFilterMask mask, int32_t nLenMin, int32_t nLenMax )
{
	// ��ȡ����
	int32_t nLen = getUTF8Length(szName);

	// ���ȼ��
	if(nLen < nLenMin)
	{
		//g_Notice.notify( g_tipsTable["notice_name_tooshort"] );
		return false;
	}
	if(nLen > nLenMax)
	{
		//g_Notice.notify( g_tipsTable["notice_name_toolong"] );
		return false;
	}

	// �ַ��Ƿ�Ϸ�
	if(!isWordCharValid(szName))
	{
		//g_Notice.notify(g_tipsTable["notice_name_invalid"]);
		return false;
	}

	// �Ƿ��ڹ��˴ʱ���
	if( isWordInFilter(szName, mask) )
	{
		//g_Notice.notify(g_tipsTable["notice_name_filter"]);
		return false;
	}

	return true;
}

bool WordFilter::isWordCharValid( const char* szName )
{
	int32_t len = strlen(szName);

	for(int32_t i=0; i<len; i++)
	{
		if( MCHECK_ACSII_1(szName[i]) 
			|| MCHECK_ACSII_2(szName[i]) 
			|| MCHECK_ACSII_3(szName[i]) 
			|| MCHECK_ACSII_4(szName[i]) 
			|| MCHECK_ASCII_Tab(szName[i]) )
		{
			return false;
		}
	}

	return true;
}

bool WordFilter::isWordAlphanumeric( const char* szName )
{
	int32_t len = strlen(szName);
	for(int32_t i=0; i<len; i++)
	{
		if( !MCHECK_ASCII_Num(szName[i]) && !MCHECK_ASCII_Alpha(szName[i]) )
		{
			return false;
		}
	}

	return true;
}

bool WordFilter::isWordInFilter( const char* szName, EFilterMask mask )
{
	// �������ַ���һ��, ��ת��ΪСд
	std::string strName = szName;
	std::transform(strName.begin(), strName.end(), strName.begin(), tolower);

	//������ַ�ĳ���
	size_t	nameLen = strName.size();

	uint16_t mod = mask & 0x5555;

	// ������˴�
	for(size_t i=0; i<_filters.size(); ++i)
	{
		// �ȹ��˴ʶ�
		if(nameLen < _filters.at(i).size())
		{
			continue;
		}

		uint16_t flag = _flags[i] & mask;
		if( flag>3 ) flag/=mod;

		switch ( flag )
		{
		case 0://����
			continue;

		case 1://ģ��ƥ��
			// �ڴ����ַ�������
			if( strName.find(_filters.at(i)) != std::string::npos )
			{
				return true;
			}
			break;

		case 2://��ȫƥ��
			// �ڴ����ַ�������
			if( nameLen==_filters.at(i).size() && strName.find(_filters.at(i)) != std::string::npos )
			{
				return true;
			}
			break;

		default:
		    break;
			//CCAssert(false, "invalid filter flag");
		}
	}

	return false;
}
